

namespace Stee.CAP8.MessageBus.Interface.Utility
{
    using System;
    using System.Text;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Serialization;

    public static class JsonSerializer
    {
        private readonly static JsonSerializerSettings settings = new JsonSerializerSettings
        {
            PreserveReferencesHandling = PreserveReferencesHandling.All,
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            TypeNameHandling = TypeNameHandling.All,
            NullValueHandling = NullValueHandling.Ignore,
            Formatting = Formatting.None,
            ContractResolver = new ReferenceResolver(),
        };


        /// <summary>
        /// Convert an object to a byte array
        /// </summary>
        /// <typeparam name="T">Object type</typeparam>
        /// <param name="obj">Object to serialize</param>
        /// <returns>Serialized object in byte array</returns>
        public static byte[] Serialize<T>(T obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            var jsonString = JsonConvert.SerializeObject(obj, settings);
            return Encoding.UTF8.GetBytes(jsonString);
        }

        /// <summary>
        /// Convert a byte array to an object
        /// </summary>
        /// <typeparam name="T">Object type</typeparam>
        /// <param name="bytes">Serialized object in byte array</param>
        /// <returns>Deserialized object</returns>
        public static T Deserialize<T>(byte[] bytes)
        {
            return (T)Deserialize(bytes, typeof(T));
        }

        /// <summary>
        /// Convert a byte array to an object
        /// </summary>
        /// <param name="bytes">Serialized object in byte array</param>
        /// <param name="type">Object type</param>
        /// <returns>Deserialized object</returns>
        public static object Deserialize(byte[] bytes, Type type)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }

            var jsonString = Encoding.UTF8.GetString(bytes);
            return JsonConvert.DeserializeObject(jsonString, type, settings);
        }
    }

    internal class ReferenceResolver : DefaultContractResolver
    {
        public override JsonContract ResolveContract(Type type)
        {
            var contract = base.ResolveContract(type);
            contract.IsReference = false;
            return contract;
        }
    }
}
